package main

import (
	"context"
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"fmt"
	"hash/fnv"
	"math"

	"github.com/redis/go-redis/v9"
)

// RedisBloomFilter 基于Redis的布隆过滤器
type RedisBloomFilter struct {
	client    *redis.Client
	key       string
	size      int
	hashFuncs []func(string) int
}

// NewRedisBloomFilter 创建Redis布隆过滤器
func NewRedisBloomFilter(client *redis.Client, key string, size int, hashCount int) *RedisBloomFilter {
	bf := &RedisBloomFilter{
		client:    client,
		key:       key,
		size:      size,
		hashFuncs: make([]func(string) int, hashCount),
	}

	// 初始化哈希函数
	bf.hashFuncs[0] = bf.hash1
	bf.hashFuncs[1] = bf.hash2
	bf.hashFuncs[2] = bf.hash3
	bf.hashFuncs[3] = bf.hash4

	return bf
}

// Add 添加元素到布隆过滤器
func (bf *RedisBloomFilter) Add(ctx context.Context, item string) error {
	pipe := bf.client.Pipeline()

	for _, hashFunc := range bf.hashFuncs {
		index := hashFunc(item) % bf.size
		pipe.SetBit(ctx, bf.key, int64(index), 1)
	}

	_, err := pipe.Exec(ctx)
	return err
}

// Contains 检查元素是否可能在布隆过滤器中
func (bf *RedisBloomFilter) Contains(ctx context.Context, item string) (bool, error) {
	pipe := bf.client.Pipeline()
	cmds := make([]*redis.IntCmd, len(bf.hashFuncs))

	for i, hashFunc := range bf.hashFuncs {
		index := hashFunc(item) % bf.size
		cmds[i] = pipe.GetBit(ctx, bf.key, int64(index))
	}

	_, err := pipe.Exec(ctx)
	if err != nil {
		return false, err
	}

	// 检查所有位是否都是1
	for _, cmd := range cmds {
		if cmd.Val() == 0 {
			return false, nil // 一定不存在
		}
	}

	return true, nil // 可能存在
}

// 哈希函数实现
func (bf *RedisBloomFilter) hash1(item string) int {
	h := fnv.New32a()
	h.Write([]byte(item))
	return int(h.Sum32())
}

func (bf *RedisBloomFilter) hash2(item string) int {
	h := md5.New()
	h.Write([]byte(item))
	hash := h.Sum(nil)
	return int(hash[0])<<24 + int(hash[1])<<16 + int(hash[2])<<8 + int(hash[3])
}

func (bf *RedisBloomFilter) hash3(item string) int {
	h := sha1.New()
	h.Write([]byte(item))
	hash := h.Sum(nil)
	return int(hash[0])<<24 + int(hash[1])<<16 + int(hash[2])<<8 + int(hash[3])
}

func (bf *RedisBloomFilter) hash4(item string) int {
	h := sha256.New()
	h.Write([]byte(item))
	hash := h.Sum(nil)
	return int(hash[0])<<24 + int(hash[1])<<16 + int(hash[2])<<8 + int(hash[3])
}

// 缓存穿透防护示例
func cachePenetrationExample() {
	ctx := context.Background()

	// 连接Redis
	client := redis.NewClient(&redis.Options{
		Addr: "localhost:6379",
	})
	defer client.Close()

	// 测试连接
	_, err := client.Ping(ctx).Result()
	if err != nil {
		fmt.Printf("Redis连接失败: %v\n", err)
		return
	}

	fmt.Println("=== Redis布隆过滤器 - 缓存穿透防护示例 ===\n")

	// 创建布隆过滤器
	expectedUsers := 10000       // 预期10000个用户
	desiredFalsePositive := 0.01 // 1%误判率
	m := int(-float64(expectedUsers) * math.Log(desiredFalsePositive) / (math.Log(2) * math.Log(2)))
	k := int(float64(m) / float64(expectedUsers) * math.Log(2))

	bf := NewRedisBloomFilter(client, "bloom:users", m, k)

	fmt.Printf("位数组大小: %d\n", m)
	fmt.Printf("哈希函数个数: %d\n", k)
	fmt.Printf("期望误判率: %.2f%%\n\n", desiredFalsePositive*100)

	// 模拟数据库中的用户ID
	databaseUsers := []string{}
	for i := 1; i <= 1000; i++ {
		databaseUsers = append(databaseUsers, fmt.Sprintf("user%d", i))
	}

	// 将数据库中的用户添加到布隆过滤器
	fmt.Println("初始化布隆过滤器...")
	for _, user := range databaseUsers {
		err := bf.Add(ctx, user)
		if err != nil {
			fmt.Printf("添加用户失败: %v\n", err)
			return
		}
	}
	fmt.Printf("已添加 %d 个用户到布隆过滤器\n\n", len(databaseUsers))

	// 模拟查询请求
	testCases := []struct {
		userID string
		exists bool
	}{
		{"user1", true},     // 存在的用户
		{"user500", true},   // 存在的用户
		{"user999", true},   // 存在的用户
		{"user9999", false}, // 不存在的用户
		{"user8888", false}, // 不存在的用户
		{"user7777", false}, // 不存在的用户
	}

	fmt.Println("模拟查询请求:")
	for _, tc := range testCases {
		exists, err := bf.Contains(ctx, tc.userID)
		if err != nil {
			fmt.Printf("查询失败: %v\n", err)
			continue
		}

		if exists {
			if tc.exists {
				fmt.Printf("  %s: 布隆过滤器显示可能存在 ✓ (实际存在)\n", tc.userID)
			} else {
				fmt.Printf("  %s: 布隆过滤器显示可能存在 ✗ (实际不存在 - 误判)\n", tc.userID)
			}
		} else {
			if tc.exists {
				fmt.Printf("  %s: 布隆过滤器显示一定不存在 ✗ (实际存在 - 错误)\n", tc.userID)
			} else {
				fmt.Printf("  %s: 布隆过滤器显示一定不存在 ✓ (实际不存在)\n", tc.userID)
			}
		}
	}

	// 性能测试
	fmt.Println("\n=== 性能测试 ===")

	// 测试10000个不存在的用户ID
	falsePositives := 0
	totalTests := 10000

	for i := 1001; i <= 1001+totalTests; i++ {
		userID := fmt.Sprintf("user%d", i)
		exists, err := bf.Contains(ctx, userID)
		if err != nil {
			fmt.Printf("查询失败: %v\n", err)
			continue
		}

		if exists {
			falsePositives++
		}
	}

	actualFalsePositiveRate := float64(falsePositives) / float64(totalTests)
	fmt.Printf("实际误判率: %.4f (%.2f%%)\n", actualFalsePositiveRate, actualFalsePositiveRate*100)
	fmt.Printf("误判次数: %d / %d\n", falsePositives, totalTests)

	// 内存使用情况
	info, err := client.MemoryUsage(ctx, "bloom:users").Result()
	if err == nil {
		fmt.Printf("布隆过滤器内存使用: %d 字节\n", info)
	}
}

func main() {
	cachePenetrationExample()
}
